local RULES_TEXT_KEY = "rules_text"
local LAST_UPDATE_KEY = "last_rules_update"

local mstore = minetest.get_mod_storage()

-- create formspec from string
local function get_formspec(text)

    local rules_fs = 'size[12,8.25]' .. "button_exit[-0.05,7.8;3,1;agree;I Agree]" ..
                         "button_exit[3,7.8;3,1;decline;I Decline]"
    if text and text ~= "" then
        rules_fs = rules_fs .. "textarea[0.25,0;12.1,9;rules;;" .. minetest.formspec_escape(text) .. "]"
    else
        rules_fs = rules_fs .. "textarea[0.25,0;12.1,9;rules;;No current rules.]"
    end
    return rules_fs
end

-- If a rules.txt exists, reads the contents and deletes the file. Returns file contents or nil if file does not exist.
local function take_new_rules()
    local rules_path = minetest.get_worldpath() .. "/rules.txt"

    local rules_file = io.open(rules_path, "r")

    if rules_file then
        local rules = rules_file:read("*a")
        rules_file:close()
        os.remove(rules_path)
        return rules
    end
end

-- Ensure the rules text in mod storage is current. Returns the text if an update has been made, otherwise nil.
local function maintain_rules()
    local rules = take_new_rules()

    -- a new rules file has been given
    if rules then
        mstore:set_string(RULES_TEXT_KEY, rules)
        mstore:set_int(LAST_UPDATE_KEY, os.time());
        return rules
    end

    return nil
end

local function get_cached_text() return mstore:get_string(RULES_TEXT_KEY) end

minetest.register_on_player_receive_fields(function(player, formname, fields)
    if formname ~= "rules" then return false end

    if fields.agree then
        -- Code for removing prompt on join
    elseif fields.decline then
        minetest.kick_player(player:get_player_name(), "Declined rules, please accept to begin playing")
    else
        minetest.show_formspec(player:get_player_name(), "rules", get_formspec(maintain_rules() or get_cached_text()))
    end

    return true
end)

-- show rules formspec on player join, unless they have already seen it
minetest.register_on_joinplayer(function(player, last_login)
    local text = maintain_rules()

    if text -- updated text
    or not last_login -- first login
    or last_login <= mstore:get_int(LAST_UPDATE_KEY) -- not seen it yet (this will be incorrect if it's before 1970)
    then
        if not text then
            -- if it's not been updated, we need to get a cached copy
            text = get_cached_text()
        end

        if text then
            local name = player:get_player_name()
            minetest.show_formspec(name, "rules", get_formspec(text))
        end
    end
end)

-- command to display server rules at any time
minetest.register_chatcommand("rules", {
    description = "Shows server rules to the player",
    func = function(name)
        local player = minetest.get_player_by_name(name)
        minetest.show_formspec(name, "rules", get_formspec(maintain_rules() or get_cached_text()))
    end
})
